using System;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Linq;
using System.IO;

namespace CheckWebsite
{
    public class WebsiteChecker
    {
        private readonly string _logFilePath;
        private readonly StringBuilder _logContent;

        public WebsiteChecker(string logFilePath)
        {
            _logFilePath = logFilePath;
            _logContent = new StringBuilder();
        }

        public async Task CheckWebsite(string hostname)
        {
            // 添加日志头部信息
            _logContent.AppendLine($"网站连接信息检查报告");
            _logContent.AppendLine($"检查时间: {DateTime.Now:yyyy-MM-dd HH:mm:ss}");
            _logContent.AppendLine($"目标域名: {hostname}");
            _logContent.AppendLine(new string('=', 60));
            _logContent.AppendLine();

            // 1. DNS解析信息
            await CheckDnsResolution(hostname);
            
            // 2. 当前DNS服务器
            CheckDnsServers();
            
            // 3. 端口检查
            await CheckPorts(hostname);
            
            // 4. SSL证书信息
            await CheckSslCertificate(hostname);
            
            // 5. HTTP响应头信息
            await CheckHttpHeaders(hostname);
            
            // 6. 网络延迟测试
            await CheckNetworkLatency(hostname);

            // 保存日志到文件
            await SaveLogToFile();
        }

        private void WriteToConsoleAndLog(string message)
        {
            Console.WriteLine(message);
            _logContent.AppendLine(message);
        }

        private async Task SaveLogToFile()
        {
            try
            {
                await File.WriteAllTextAsync(_logFilePath, _logContent.ToString(), Encoding.UTF8);
            }
            catch (Exception ex)
            {
                WriteToConsoleAndLog($"保存日志文件失败: {ex.Message}");
            }
        }

        private async Task CheckDnsResolution(string hostname)
        {
            WriteToConsoleAndLog("1. DNS解析信息:");
            WriteToConsoleAndLog("   " + new string('-', 30));
            
            try
            {
                var addresses = await Dns.GetHostAddressesAsync(hostname);
                
                WriteToConsoleAndLog($"   主机名: {hostname}");
                WriteToConsoleAndLog($"   解析到的IP地址:");
                
                foreach (var address in addresses)
                {
                    WriteToConsoleAndLog($"   - {address} ({address.AddressFamily})");
                    
                    // 反向DNS解析
                    try
                    {
                        var reverseDns = await Dns.GetHostEntryAsync(address);
                        if (reverseDns.HostName != address.ToString())
                        {
                            WriteToConsoleAndLog($"     反向DNS: {reverseDns.HostName}");
                        }
                    }
                    catch
                    {
                        // 反向DNS解析失败，忽略
                    }
                }
            }
            catch (Exception ex)
            {
                WriteToConsoleAndLog($"   DNS解析失败: {ex.Message}");
            }
            
            WriteToConsoleAndLog("");
        }

        private void CheckDnsServers()
        {
            WriteToConsoleAndLog("2. 当前DNS服务器:");
            WriteToConsoleAndLog("   " + new string('-', 30));
            
            try
            {
                var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces()
                    .Where(ni => ni.OperationalStatus == OperationalStatus.Up)
                    .Where(ni => ni.NetworkInterfaceType != NetworkInterfaceType.Loopback);

                foreach (var ni in networkInterfaces)
                {
                    var ipProps = ni.GetIPProperties();
                    var dnsServers = ipProps.DnsAddresses;
                    
                    if (dnsServers.Count > 0)
                    {
                        WriteToConsoleAndLog($"   网络接口: {ni.Name}");
                        WriteToConsoleAndLog($"   类型: {ni.NetworkInterfaceType}");
                        WriteToConsoleAndLog($"   DNS服务器:");
                        
                        foreach (var dns in dnsServers)
                        {
                            WriteToConsoleAndLog($"   - {dns}");
                        }
                        WriteToConsoleAndLog("");
                    }
                }
            }
            catch (Exception ex)
            {
                WriteToConsoleAndLog($"   获取DNS服务器失败: {ex.Message}");
            }
        }

        private async Task CheckPorts(string hostname)
        {
            WriteToConsoleAndLog("3. 端口检查:");
            WriteToConsoleAndLog("   " + new string('-', 30));
            
            var commonPorts = new[] { 80, 443 };
            
            foreach (var port in commonPorts)
            {
                try
                {
                    using var client = new TcpClient();
                    await client.ConnectAsync(hostname, port);
                    
                    if (client.Connected)
                    {
                        string service = GetServiceName(port);
                        WriteToConsoleAndLog($"   端口 {port} (TCP): 开放 - {service}");
                        client.Close();
                    }
                }
                catch
                {
                    WriteToConsoleAndLog($"   端口 {port} (TCP): 关闭");
                }
            }
            
            WriteToConsoleAndLog("");
        }

        private string GetServiceName(int port)
        {
            return port switch
            {
                80 => "HTTP",
                443 => "HTTPS",
                21 => "FTP",
                22 => "SSH",
                25 => "SMTP",
                53 => "DNS",
                110 => "POP3",
                143 => "IMAP",
                993 => "IMAPS",
                995 => "POP3S",
                8080 => "HTTP-Alt",
                8443 => "HTTPS-Alt",
                _ => "Unknown"
            };
        }

        private async Task CheckSslCertificate(string hostname)
        {
            WriteToConsoleAndLog("4. SSL证书信息:");
            WriteToConsoleAndLog("   " + new string('-', 30));
            
            try
            {
                using var client = new TcpClient();
                await client.ConnectAsync(hostname, 443);
                
                using var sslStream = new SslStream(client.GetStream(), false, 
                    (sender, certificate, chain, sslPolicyErrors) => true);
                
                await sslStream.AuthenticateAsClientAsync(hostname);
                
                var cert = sslStream.RemoteCertificate as X509Certificate2;
                if (cert != null)
                {
                    WriteToConsoleAndLog($"   证书主题: {cert.Subject}");
                    WriteToConsoleAndLog($"   颁发者: {cert.Issuer}");
                    WriteToConsoleAndLog($"   有效期从: {cert.NotBefore:yyyy-MM-dd HH:mm:ss}");
                    WriteToConsoleAndLog($"   有效期至: {cert.NotAfter:yyyy-MM-dd HH:mm:ss}");
                    WriteToConsoleAndLog($"   序列号: {cert.SerialNumber}");
                    WriteToConsoleAndLog($"   指纹: {cert.Thumbprint}");
                    WriteToConsoleAndLog($"   密钥算法: {cert.SignatureAlgorithm.FriendlyName}");
                    try
                    {
                        var rsaKey = cert.GetRSAPublicKey();
                        if (rsaKey != null)
                        {
                            WriteToConsoleAndLog($"   密钥长度: {rsaKey.KeySize} 位");
                        }
                    }
                    catch
                    {
                        WriteToConsoleAndLog($"   密钥长度: 无法获取");
                    }
                    
                    // 检查证书是否即将过期
                    var daysUntilExpiry = (cert.NotAfter - DateTime.Now).Days;
                    if (daysUntilExpiry < 30)
                    {
                        WriteToConsoleAndLog($"   ⚠️  警告: 证书将在 {daysUntilExpiry} 天后过期！");
                    }
                }
            }
            catch (Exception ex)
            {
                WriteToConsoleAndLog($"   SSL证书检查失败: {ex.Message}");
            }
            
            WriteToConsoleAndLog("");
        }

        private async Task CheckHttpHeaders(string hostname)
        {
            WriteToConsoleAndLog("5. HTTP响应头信息:");
            WriteToConsoleAndLog("   " + new string('-', 30));
            
            // 检查HTTPS
            try
            {
                using var httpClient = new HttpClient();
                httpClient.Timeout = TimeSpan.FromSeconds(10);
                
                var response = await httpClient.GetAsync($"https://{hostname}", HttpCompletionOption.ResponseHeadersRead);
                
                WriteToConsoleAndLog($"   HTTPS状态码: {(int)response.StatusCode} {response.StatusCode}");
                WriteToConsoleAndLog($"   服务器: {response.Headers.Server?.ToString() ?? "未知"}");
                WriteToConsoleAndLog($"   内容类型: {response.Content.Headers.ContentType?.ToString() ?? "未知"}");
                WriteToConsoleAndLog($"   内容长度: {response.Content.Headers.ContentLength?.ToString() ?? "未知"}");
                
                WriteToConsoleAndLog("   响应头:");
                foreach (var header in response.Headers)
                {
                    WriteToConsoleAndLog($"   - {header.Key}: {string.Join(", ", header.Value)}");
                }
            }
            catch (Exception ex)
            {
                WriteToConsoleAndLog($"   HTTPS检查失败: {ex.Message}");
            }
            
            // 检查HTTP
            try
            {
                using var httpClient = new HttpClient();
                httpClient.Timeout = TimeSpan.FromSeconds(10);
                
                var response = await httpClient.GetAsync($"http://{hostname}", HttpCompletionOption.ResponseHeadersRead);
                
                WriteToConsoleAndLog($"   HTTP状态码: {(int)response.StatusCode} {response.StatusCode}");
            }
            catch (Exception ex)
            {
                WriteToConsoleAndLog($"   HTTP检查失败: {ex.Message}");
            }
            
            WriteToConsoleAndLog("");
        }

        private async Task CheckNetworkLatency(string hostname)
        {
            WriteToConsoleAndLog("6. 网络延迟测试:");
            WriteToConsoleAndLog("   " + new string('-', 30));
            
            try
            {
                var addresses = await Dns.GetHostAddressesAsync(hostname);
                var ipAddress = addresses.FirstOrDefault();
                
                if (ipAddress != null)
                {
                    using var ping = new Ping();
                    var times = new List<long>();
                    
                    WriteToConsoleAndLog($"   目标IP: {ipAddress}");
                    WriteToConsoleAndLog("   Ping测试 (5次):");
                    
                    for (int i = 0; i < 5; i++)
                    {
                        try
                        {
                            var reply = await ping.SendPingAsync(ipAddress, 5000);
                            if (reply.Status == IPStatus.Success)
                            {
                                times.Add(reply.RoundtripTime);
                                WriteToConsoleAndLog($"   #{i + 1}: {reply.RoundtripTime}ms");
                            }
                            else
                            {
                                WriteToConsoleAndLog($"   #{i + 1}: 超时");
                            }
                        }
                        catch
                        {
                            WriteToConsoleAndLog($"   #{i + 1}: 失败");
                        }
                        
                        await Task.Delay(1000); // 1秒间隔
                    }
                    
                    if (times.Count > 0)
                    {
                        WriteToConsoleAndLog($"   平均延迟: {times.Average():F1}ms");
                        WriteToConsoleAndLog($"   最小延迟: {times.Min()}ms");
                        WriteToConsoleAndLog($"   最大延迟: {times.Max()}ms");
                    }
                }
            }
            catch (Exception ex)
            {
                WriteToConsoleAndLog($"   网络延迟测试失败: {ex.Message}");
            }
            
            WriteToConsoleAndLog("");
        }
    }
}
